Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[hdpowerview] Add support for repeaters #12061

Merged
merged 8 commits into from
Jan 24, 2022

Conversation

jlaur
Copy link
Contributor

@jlaur jlaur commented Jan 16, 2022

Fixes #12060

Signed-off-by: Jacob Laursen [email protected]

Add support for Hunter Douglas PowerView Repeaters.

Supporting the Repeater as a thing makes it possible to:

  • Enable/disable blinking during commands. For example this can be used to disable at night when repeater is in a bedroom.
  • Flash repeater LED's on request. For example this could be used in combination with a motion sensor to provide position lighting at night.
  • See firmware version information.

Technical approach

  • New thing type repeater created (with discovery support).
  • Repeaters are polled every 5 minutes to synchronize "blink enabled" state when done from PowerView app or other integrations.
  • When receiving repeater information, firmware information is also obtained and set as property.
  • When identify channel is triggered, response received will be used for immediate update (in between 5 minute polls).
  • Each repeater thing will have its own scheduled job. This could be slightly optimized by letting the hub fetch data for all repeaters in same job. On the other hand it would mean more direct dependencies between bridge handler and repeater thing handler. Usually I would expect no more than one or two repeaters in a relatively big house.

Result

Thing

image

Channels

image

Additional refactoring

After testing with frequent binding restarts and configuration changes, I noticed a few warnings on follow-up log inspection:

2022-01-18 20:01:04.197 [TRACE] [rview.internal.HDPowerViewWebTargets] - API command GET http://192.168.0.239/api/shades/0?refresh=true
2022-01-18 20:01:04.240 [WARN ] [rview.internal.HDPowerViewWebTargets] - Hub returned HTTP 403 Forbidden
2022-01-18 20:01:04.245 [WARN ] [rnal.handler.HDPowerViewShadeHandler] - Unexpected error: HTTP 403 error

I have not yet found the root cause, and I do not suspect the changes in this PR to be causing this behavior. But nevertheless I would like to get to the bottom of this, so as first step I simplified the configuration ID handling to be more robust by changing it from string to integer and adding validation. Doing this for the new repeater thing was fully within the scope of this PR, but for consistency I decided to perform the same refactoring for the shade thing. I have tested backwards compatibility for the change by creating a thing with version 3.2 of the binding from UI, then migrated to the PR version and verified that thing still works correctly.

@jlaur jlaur added the enhancement An enhancement or new feature for an existing add-on label Jan 16, 2022
@jlaur jlaur requested a review from andrewfg January 16, 2022 15:02
@andrewfg
Copy link
Contributor

@jlaur unfortunately I don't have any repeaters so I cannot test the new functionality, but I will at least check that existing functionality (normal shades) has not been broken :)

@jlaur
Copy link
Contributor Author

jlaur commented Jan 16, 2022

unfortunately I don't have any repeaters so I cannot test the new functionality

I would say fortunately. Not needing them is much desired. :-)

I will at least check that existing functionality (normal shades) has not been broken :)

Thanks. I have it running in production now, but would like to run it for some more time before marking as ready. Since it's a new thing type everything is quite isolated and existing functionality should not be affected much. But I already found an assumption in HDPowerViewHubHandler about all things being of type shade, so you never know.

@jlaur jlaur marked this pull request as ready for review January 16, 2022 19:32
@jlaur jlaur requested a review from andylintner as a code owner January 16, 2022 19:32
jlaur added 2 commits January 17, 2022 13:46
Fixes openhab#12060

Signed-off-by: Jacob Laursen <[email protected]>
Signed-off-by: Jacob Laursen <[email protected]>
@jlaur jlaur force-pushed the 12060-hdpowerview-repeater-suppport branch from df5b2d9 to 9356c99 Compare January 17, 2022 12:46
@andrewfg
Copy link
Contributor

A trivial issue, but one of your JUnit tests is issuing an unexpected logger message..

image

@jlaur
Copy link
Contributor Author

jlaur commented Jan 17, 2022

A trivial issue, but one of your JUnit tests is issuing an unexpected logger message..

I know, but didn't think it would be a problem since it's not considered a warning, but just two lines of console output? I'll have another look at this and see if I can mock logger somehow. Please don't let it block this PR as it was introduced by #11853 which is already merged. I'll provide a new PR for this issue and link it to #11852 once I have found a solution.

@andrewfg
Copy link
Contributor

andrewfg commented Jan 17, 2022

see if I can mock logger somehow

Perhaps one can set a lower logger level when running JUnit tests (e.g. log:set ERROR or even log:set OFF), or add an argument to the method being called (e.g. method(..., boolean loggingEnabled) -- although this latter is a bit clunky..)

EDIT: https://logging.apache.org/log4j/log4j-2.4/faq.html#set_logger_level_from_code

don't let it block this PR

Ok with me.

@jlaur
Copy link
Contributor Author

jlaur commented Jan 17, 2022

see if I can mock logger somehow

Perhaps one can set a lower logger level when running JUnit tests (e.g. log:set ERROR or even log:set OFF), or add an argument to the method being called (e.g. method(..., boolean loggingEnabled) -- although this latter is a bit clunky..)

I'm definitely against the latter. As for log level manipulration, I could imagine setting log level this way could introduce problems with parallel test runs, but not sure. Also it wouldn't be able to test if something was indeed logged.

Initially I tried to create some mocks based on LoggerFactory.getILoggerFactory() but failed. I looked into a few other approaches, and ended up with this static scoped one as being the cleanest and simplest for this scenario:

    @Test
    public void emptyListWhenNoSceneForScheduledEvent() {
        try (MockedStatic<LoggerFactory> staticMock = mockStatic(LoggerFactory.class)) {
            @Nullable
            final Logger logger = mock(Logger.class);
            staticMock.when(() -> LoggerFactory.getLogger(any(Class.class))).thenReturn(logger);

            builder = AutomationChannelBuilder.create(translationProvider, CHANNEL_GROUP_UID);
            ScheduledEvent scheduledEvent = createScheduledEventWithSceneCollection(
                    ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
            List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
            List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();

            assertEquals(0, channels.size());
            Logger verifyLogger = verify(logger);
            assertNotNull(verifyLogger);
            if (verifyLogger != null) {
                verifyLogger.warn(any(String.class), any(), any());
            }
        }
    }

verify() can of course be adapted to needs, for this PoC it just verifies that any warning with two additional parameters is logged.

I was able to run it after modifying pom.xml for the binding:
image

Now wondering if mockito-inline could/should be added to:
https://github.com/openhab/openhab-core/blob/main/bom/test/pom.xml

which is referenced from here:
https://github.com/openhab/openhab-addons/blob/main/bom/test-index/pom.xml

@wborn - any opinion/advice here, i.e. if it would be okay to include mockito-inline instead of mockito-core, and if yes, in which POM? Eventually mockito-inline will be abandoned and we'll need to go back to mockito-core when integrated. See:

@andrewfg
Copy link
Contributor

IMHO you should certainly not add a mockito dependency to the binding pom..

Perhaps another solution is to have JUnit call an inner class for the test, that does not do any logging, but throws an exception instead; and then let the binding itself call an outer wrapper class that catches that exception and logs the warning.

PS notwithstanding the above, I can tell you that the jar for this build has been running on my operative system for 6 hours or so, and seems to be working as it should. (Although, actually I personally find it rather uncanny that when one moves the shades, the OH UI updates to the new position immediately — even though the shades have not actually achieved that position yet..)

@jlaur
Copy link
Contributor Author

jlaur commented Jan 18, 2022

IMHO you should certainly not add a mockito dependency to the binding pom..

We fully agree on this. It was a Proof-of-Concept, suggestion was to add it to the linked POM:
https://github.com/openhab/openhab-core/blob/main/bom/test/pom.xml

Perhaps another solution is to have JUnit call an inner class for the test, that does not do any logging, but throws an exception instead; and then let the binding itself call an outer wrapper class that catches that exception and logs the warning.

I'm not sure I understand what you mean by inner/outer classes, do you mean changing AutomationChannelBuilder itself? I rather think it should stay as a single class without any need to extract that private method to a new class just for sake of testing. Also would not throw/catch exceptions within a loop to handle such simple internal cases. Instead this could be changed to some try* pattern, though. The public method should be enough for testing that functionality within the private method also, we just need to mock the logger, and as I've shown, this is certainly possible.

PS notwithstanding the above, I can tell you that the jar for this build has been running on my operative system for 6 hours or so, and seems to be working as it should.

Thanks for giving it a shot!

(Although, actually I personally find it rather uncanny that when one moves the shades, the OH UI updates to the new position immediately — even though the shades have not actually achieved that position yet..)

Hmm, I think you introduced that behavior in #11698? It was slightly changed in #12002 by using the response directly instead of requesting positions again by sending a new request. I'm open for discussing this, it could even easily be reverted/changed/refined. However, please consider:

  • We have no way of knowing how long it takes to move the shade, i.e. when it will reach its target position.
  • The position will be updated in the hub immediately.

So with the new approach we introduced, we'll synchronize with the hub immediately. Previously (before your change) it would be synchronized at a random moment after moving the shade, i.e. upon next poll. So if next poll would be one second after moving the shade, it would be updated then. But it could also have to wait up to one minute.

@andrewfg
Copy link
Contributor

not sure I understand what you mean by inner/outer classes

Oops. I meant to say “inner/outer method”. Sorry for the confusion.

introduced that behavior in #11698?

Yes indeed. But it was not my request, and came rather from the guy who opened the issue. As said, I personally find it uncanny … but I can live with it..

@jlaur
Copy link
Contributor Author

jlaur commented Jan 18, 2022

@andrewfg - I did a new commit, 271d027, today after some suspicious warnings in my logs. I still don't know what caused that, but I'm keeping an eye on it. Have you (ever) seen anything like that? Unfortunately I'm not keeping old logs, so can't check first occurrence. See last section in PR description for details.

@wborn
Copy link
Member

wborn commented Jan 19, 2022

any opinion/advice here, i.e. if it would be okay to include mockito-inline instead of mockito-core

I always stay away from experimental or incubating features because they can break with any upgrade. We've seen incubating mockito/junit functionality break before (openhab/org.openhab.binding.zwave#1689 (comment)).

@jlaur
Copy link
Contributor Author

jlaur commented Jan 20, 2022

@andrewfg - would you be able to review this PR before assigning it to maintainers for review? Asking because I now prepared a fix for #12071 but it will conflict, so will hold that back for a while.

Copy link
Contributor

@andrewfg andrewfg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a repeater so could not test that Thing type; however I can confirm that the original Shade Things are (still) working.

@jlaur jlaur requested a review from a team January 20, 2022 18:12
@jlaur
Copy link
Contributor Author

jlaur commented Jan 21, 2022

@lolodomo - looking at recent hdpowerview PR review history, would this be something for you to have a look at? :-)

@jlaur
Copy link
Contributor Author

jlaur commented Jan 24, 2022

@openhab/add-ons-maintainers - anyone willing to review this PR? I have some additional work planned for another PR, but need this one merged first.

@andrewfg andrewfg requested a review from lolodomo January 24, 2022 16:23
@fwolter
Copy link
Member

fwolter commented Jan 24, 2022

@openhab/add-ons-maintainers - anyone willing to review this PR? I have some additional work planned for another PR, but need this one merged first.

You could base your work on this PR's branch and add the "awaiting other PR" label for your new PR.

@jlaur
Copy link
Contributor Author

jlaur commented Jan 24, 2022

You could base your work on this PR's branch and add the "awaiting other PR" label for your new PR.

True. I'm just not a fan of such dependency chains as there could also be other things merged in the meantime. Or this one might not be merged at all. So when preparing small changes with big risk of conflicts, I tend to prefer waiting. But thanks for the hint!

@jlaur
Copy link
Contributor Author

jlaur commented Jan 24, 2022

The command looks good in general. Did you try to set the auto update policy to veto to prevent the necessity to reset the Channel value manually? See https://www.openhab.org/docs/developer/bindings/thing-xml.html#auto-update-policies

No, was unaware - thanks. Now after reading it, I think it will work better with current approach, since state will be kept for the duration of the blinking period. This looks kind of cool in the UI. :-) I don't think it's possible to set a timer using the policies?

@fwolter
Copy link
Member

fwolter commented Jan 24, 2022

There's no timer for update policies I'm aware of. Your approach is good to go.

@jlaur jlaur requested a review from fwolter January 24, 2022 21:12
Copy link
Member

@fwolter fwolter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fwolter fwolter merged commit 9d361c1 into openhab:main Jan 24, 2022
@fwolter fwolter added this to the 3.3 milestone Jan 24, 2022
nemerdaud pushed a commit to nemerdaud/openhab-addons that referenced this pull request Jan 28, 2022
* Add support for repeaters.

Fixes openhab#12060

Signed-off-by: Jacob Laursen <[email protected]>

* Simplify thing type filtering.

Signed-off-by: Jacob Laursen <[email protected]>

* Improve robustness of configuration ID validation/initialization.

Signed-off-by: Jacob Laursen <[email protected]>

* Convert repeater-identify to command channel.

Signed-off-by: Jacob Laursen <[email protected]>

* Fix logged warning.

Signed-off-by: Jacob Laursen <[email protected]>

* Skip unneeded bridge status logic.

Signed-off-by: Jacob Laursen <[email protected]>

* Skip redundant logging.

Signed-off-by: Jacob Laursen <[email protected]>

* Fix chanenl type label for blinking enabled.

Signed-off-by: Jacob Laursen <[email protected]>
@jlaur
Copy link
Contributor Author

jlaur commented Feb 10, 2022

@lolodomo - would it be possible for you to synchronize hdpowerview_da_properties with Crowdin as this was mistakenly included in this PR and a few others? Current situation is that Danish strings already exist in the repository, but they are not available in Crowdin.

@lolodomo
Copy link
Contributor

lolodomo commented Feb 10, 2022

would it be possible for you to synchronize hdpowerview_da_properties with Crowdin as this was mistakenly included in this PR and a few others? Current situation is that Danish strings already exist in the repository, but they are not available in Crowdin.

Is it ok to simply override all Crowdin translations by those in Github?

@jlaur
Copy link
Contributor Author

jlaur commented Feb 10, 2022

Is it ok to simply override all Crowdin translations by those in Github?

Yes, at least the Danish ("_da") ones which seems missing in Crowdin. I'm not sure if there are any other translations in Crowdin for hdpowerview not yet in the repository, but probably not? Can't figure out how to see all translations for a single bundle.

@lolodomo
Copy link
Contributor

Translations uploaded in Crowdin. Only 29% of translations are completed.

@jlaur
Copy link
Contributor Author

jlaur commented Feb 10, 2022

Translations uploaded in Crowdin.

Thanks!

Do we have any guidelines or documentation for the processes involving Crowdin synchronization/workflows? By now I understand that default (English) properties are one-way synced from repository to Crowdin. Then translations are synced back to repository, and it creates some kind of trouble if they are going the other way - perhaps simply because there is no automation for that? But some details would be nice for the understanding. Also what it takes to assess if a Crowin PR is safe to merge. I can help write it if it doesn't exist, but first I would need some more knowledge. :)

@lolodomo
Copy link
Contributor

lolodomo commented Feb 10, 2022

Default (English) properties are one-way automatically synced from repository to Crowdin.
Non default properties are one-way automatically synced from Crowdin to repository when translations are fully completed in Crowdin.
Problems are introduced if non default translations are merged directly in repository (not coming from Crowdin). That is the reason why we have to reject PRs including such translations.
In Crowdin, like I did for the HDPowerview Danish translations, you have a command to upload translations from a file.
@wborn and @cweitkamp are the ones who have the best knowledge of all of that for the project. Please correct me if needed.

NickWaterton pushed a commit to NickWaterton/openhab-addons that referenced this pull request Apr 27, 2022
* Add support for repeaters.

Fixes openhab#12060

Signed-off-by: Jacob Laursen <[email protected]>

* Simplify thing type filtering.

Signed-off-by: Jacob Laursen <[email protected]>

* Improve robustness of configuration ID validation/initialization.

Signed-off-by: Jacob Laursen <[email protected]>

* Convert repeater-identify to command channel.

Signed-off-by: Jacob Laursen <[email protected]>

* Fix logged warning.

Signed-off-by: Jacob Laursen <[email protected]>

* Skip unneeded bridge status logic.

Signed-off-by: Jacob Laursen <[email protected]>

* Skip redundant logging.

Signed-off-by: Jacob Laursen <[email protected]>

* Fix chanenl type label for blinking enabled.

Signed-off-by: Jacob Laursen <[email protected]>
Signed-off-by: Nick Waterton <[email protected]>
andan67 pushed a commit to andan67/openhab-addons that referenced this pull request Nov 6, 2022
* Add support for repeaters.

Fixes openhab#12060

Signed-off-by: Jacob Laursen <[email protected]>

* Simplify thing type filtering.

Signed-off-by: Jacob Laursen <[email protected]>

* Improve robustness of configuration ID validation/initialization.

Signed-off-by: Jacob Laursen <[email protected]>

* Convert repeater-identify to command channel.

Signed-off-by: Jacob Laursen <[email protected]>

* Fix logged warning.

Signed-off-by: Jacob Laursen <[email protected]>

* Skip unneeded bridge status logic.

Signed-off-by: Jacob Laursen <[email protected]>

* Skip redundant logging.

Signed-off-by: Jacob Laursen <[email protected]>

* Fix chanenl type label for blinking enabled.

Signed-off-by: Jacob Laursen <[email protected]>
andrasU pushed a commit to andrasU/openhab-addons that referenced this pull request Nov 12, 2022
* Add support for repeaters.

Fixes openhab#12060

Signed-off-by: Jacob Laursen <[email protected]>

* Simplify thing type filtering.

Signed-off-by: Jacob Laursen <[email protected]>

* Improve robustness of configuration ID validation/initialization.

Signed-off-by: Jacob Laursen <[email protected]>

* Convert repeater-identify to command channel.

Signed-off-by: Jacob Laursen <[email protected]>

* Fix logged warning.

Signed-off-by: Jacob Laursen <[email protected]>

* Skip unneeded bridge status logic.

Signed-off-by: Jacob Laursen <[email protected]>

* Skip redundant logging.

Signed-off-by: Jacob Laursen <[email protected]>

* Fix chanenl type label for blinking enabled.

Signed-off-by: Jacob Laursen <[email protected]>
Signed-off-by: Andras Uhrin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement An enhancement or new feature for an existing add-on
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[hdpowerview] Repeater support
5 participants